#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QDebug>

#include <QDomDocument>
#include <QDomNode>
#include <QTableWidgetItem>
#include <QTextStream>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

//    this->readXML();
//    this->getElementByTagName();
//    this->xmlToTable();
    this->createXml();
}

void Widget::readXML()
{
    // 1. 从XML文档中读取内容并转换为 DOM树
    // 1) 创建QDomDocument 对象
    QDomDocument doc;

    // 2) 以只读方式打开xml文件
    QFile file("E:/Projects/QtProjects/study/qt-12/gdg.xml");
    file.open(QIODevice::ReadOnly);

    // 3) 转换xml文档内容为DOM树
    if(!doc.setContent(&file))
    {
        qDebug() << "载入xml文档失败";
        file.close();
        return ;
    }
    else
    {
        qDebug() << "载入成功";
        file.close();
    }

    // 2. 从DOM树中读取头部
    // 节点类型：
    //    1   元素节点（标签节点）
    //    2   属性节点
    //    3   文本节点
    //    7   头部
//    QDomNode head = doc.firstChild();
//    qDebug() << head.nodeName() << head.nodeType() << head.nodeValue();

    // 3. 获取根节点
    QDomElement rootEle = doc.documentElement();
    qDebug() << rootEle.nodeName() << rootEle.nodeType() << rootEle.nodeValue();
    qDebug() << rootEle.tagName() << rootEle.text();

    // 4. 获取根标签的子标签 --- name
    // 通过firstChild方法获取第一个子标签，得到QDomNode 对象（本质是element）
    QDomNode nameNode = rootEle.firstChild();
    // 通过 toElement 方法转为 QDomElement 类型
    QDomElement nameEle = nameNode.toElement();
    // 将 QDomNode 转换为 QDomElement 之后，就能获取标签中的文本和属性中的值了
    qDebug() << nameEle.tagName() << nameEle.text() << nameEle.attribute("id");

    // 通过 name节点，找下一个兄弟节点
    QDomElement ageEle = nameEle.nextSiblingElement();
    qDebug() << ageEle.text();

    // 通过 age 找son
    QDomElement sonEle = ageEle.nextSiblingElement();


    // 通过循环读取son中的三个节点
    QDomNode node = sonEle.firstChild();
    while (node.isElement())
    {
        QDomElement ele = node.toElement();
        qDebug() << ele.text();
        node = ele.nextSiblingElement();
    }
}

// 通过标签名来获取标签对象
// 注意：通过标签名来获取标签对象是不分层级的
void Widget::getElementByTagName()
{
    // 1. 将xml文件转为DOM树
    QDomDocument doc;
    QFile file("E:/Projects/QtProjects/study/qt-12/gdg.xml");
    file.open(QIODevice::ReadOnly);
    doc.setContent(&file);
    file.close();

    // 2. 使用elementsByTagName 根据标签名来获取DOM中所有的同名标签
    QDomNodeList list = doc.elementsByTagName("name");
    for(int i = 0; i < list.size(); i++)
    {
        QDomElement tmp = list.at(i).toElement();
        qDebug() << tmp.text();
    }
}

void Widget::xmlToTable()
{
    QDomDocument doc;
    QFile file("E:/Projects/QtProjects/study/qt-12/bookstore.xml");
    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "xml文件加载失败";
        file.close();
        return;
    }
    else
    {
        qDebug() << "xml文件加载成功";
        doc.setContent(&file);
        file.close();
    }

    // 获取所有 <book> 节点
    QDomNodeList bookList = doc.elementsByTagName("book");

    // 设置表格的行数和列数
    ui->tableWidget->setRowCount(bookList.size());
    ui->tableWidget->setColumnCount(4);
    ui->tableWidget->setHorizontalHeaderLabels({"书名", "作者", "售价", "出版日期"});

    // 遍历 <book> 列表
    for(int i = 0; i < bookList.size(); i++)
    {
        QDomNode bookNode = bookList.at(i);
        QDomNodeList childNodes = bookNode.childNodes();  // 获取当前 <book> 节点的所有子节点

        // 依次提取子节点的值
        QString bookName = childNodes.at(0).toElement().text();
        QString author = childNodes.at(1).toElement().text();
        QString price = childNodes.at(2).toElement().text();
        QString pubDate = childNodes.at(3).toElement().text();

        // 将数据填入表格
        ui->tableWidget->setItem(i, 0, new QTableWidgetItem(bookName));
        ui->tableWidget->setItem(i, 1, new QTableWidgetItem(author));
        ui->tableWidget->setItem(i, 2, new QTableWidgetItem(price));
        ui->tableWidget->setItem(i, 3, new QTableWidgetItem(pubDate));
    }
}

void Widget::createXml()
{
    // 1. 创建一个空的 QDomDocument 对象
    QDomDocument doc;

    // 2. 创建头并加入到 QDomDocument 中
    QDomProcessingInstruction head = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
    doc.appendChild(head);
    // 3. 创建根标签并加入到 QDomDocument 中
    QDomElement rootEle = doc.createElement("gdg");
    doc.appendChild(rootEle);

    // 4. 向根标签中添加子标签
    // 1) 创建子标签
    // 2) 向标签中添加属性
    // 3) 创建文本节点，并将文本节点添加到子标签中
    // 4) 子标签添加到根节点中
    QDomElement nameEle = doc.createElement("name");
    nameEle.setAttribute("id", "10001");
    QDomText nameTxt = doc.createTextNode("郭德纲");
    nameEle.appendChild(nameTxt);
    rootEle.appendChild(nameEle);

    QDomElement ageEle = doc.createElement("age");
    QDomText ageTxt = doc.createTextNode("50");
    ageEle.appendChild(ageTxt);
    rootEle.appendChild(ageEle);

    // 5. 创建文本流，将doc对象写入到xml文件中
    QFile file("e:/gdg.xml");
    file.open(QIODevice::WriteOnly);

    QTextStream out(&file);
    doc.save(out, 4);
}

Widget::~Widget()
{
    delete ui;
}
